/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.admin.client.components;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.elf.gwt.admin.client.AdminComponentController;
import com.elf.gwt.admin.client.GWTCommerceConstants;
import com.elf.gwt.common.client.GWTCommerceCommonConstants;
import com.elf.gwt.common.client.access.RequestParameter;
import com.elf.gwt.common.client.model.AccountMetaModel;
import com.elf.gwt.common.client.model.AccountModel;
import com.elf.gwt.common.client.model.AddressModel;
import com.elf.gwt.common.client.model.CountryModel;
import com.elf.gwt.common.client.utils.CommonUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

/**
 *
 */
public class EditAccountComponent extends JSONServerComponent
{	
	public static final String CreateAccount = "CreateAccount";
	public static final String EditAccount = "EditAccount";
	public static final String DeleteAccount = "DeleteAccount";
	public static final String AddressBook = "AddressBook";
	public static final String DeleteAddress = "DeleteAddress";

	protected int selectedGroupId = 0;
	protected int selectedAccountId = 0;
	protected AccountMetaModel accountMetaModel;
	protected AccountModel accountModel;

	protected HashMap<String, Widget> elements = null;
	protected HashMap<String, Widget> addressElements = null;

	protected String action = "";

	protected Button backButton = null;
	protected Button deleteButton = null;
	protected ListBox countryListBox = null;
	protected ListBox stateListBox;
	protected DialogBox dialogBox;

	EditAccountComponent(AdminComponentController controller, String stylePrefix)
	{
		super(controller, stylePrefix);
		setupTimer();
		elements = new HashMap<String, Widget>();
		addressElements = new HashMap<String, Widget>();
		accountModel = new AccountModel();

		deleteButton = new Button("delete", deleteHandler);
		deleteButton.addStyleName("ComponentLink");
		backButton = new Button("back", backHandler);
		backButton.addStyleName("ComponentLink");
	}

	public void additionalRequestParameters()
	{
		addRequestParameter(new RequestParameter ("editAccountId", selectedAccountId));
		addRequestParameter(new RequestParameter("action", action));

		if (action.equals(CreateAccount) || action.equals(EditAccount) || action.equals(DeleteAccount)) {
			Iterator<String> iterElements = elements.keySet().iterator();
			while (iterElements.hasNext())
			{
				String key = iterElements.next();
				Widget widget = elements.get(key);
				String value = CommonUtils.getValue(widget);
				addRequestParameter(new RequestParameter(key, value));
			} 
		}

		Iterator<String> iterElements = addressElements.keySet().iterator();
		while (iterElements.hasNext())
		{
			String key = iterElements.next();
			Widget widget = addressElements.get(key);
			String value = CommonUtils.getValue(widget);
			addRequestParameter(new RequestParameter(key, value));
		} 

		action = "";
	}

	protected void buildMetaModel(JSONObject jsonObject) throws Exception
	{
		accountMetaModel = new AccountMetaModel(jsonObject);
	}

	protected void buildModel(JSONObject jsonObject) throws Exception
	{
		accountModel.update(jsonObject);
	}

	public void buildFromModel() throws Exception
	{
		clear();
		elements.clear();
		addressElements.clear();
		GWTCommerceCommonConstants commonConstants = controller.getCommonConstants();
		GWTCommerceConstants constants = adminController.getAdminConstants();

		HorizontalPanel buttonPanel = new HorizontalPanel();
		buttonPanel.setStyleName("ZButtons");
		buttonPanel.add(backButton);
		buttonPanel.add(new InlineHTML("&nbsp;&nbsp;"));
		add(buttonPanel);
		add(new HTML("<br/><br/><br/>"));

		int id = accountModel.getErrorCode();
		if (id != 0) {
			InlineHTML warningLabel = new InlineHTML();
			warningLabel.setStyleName("WarningLabel");
			warningLabel.addStyleName(handle + "WarningLabel");
			add(warningLabel);

			if (id == 1)
			{
				warningLabel.setHTML("<span class = \"successLabel\">"+commonConstants.Success()+"</span>");
			}
			else if (id == -43)
			{
				warningLabel.setHTML(constants.AccountComponentEmailAddressCheckError() + "<br/>");
			}
			else if (id == -50)
			{
				warningLabel.setHTML(constants.AccountComponentAccountAlreadyExists() + "<br/>");
			}
			else if (id == -60)
			{
				warningLabel.setHTML(constants.AccountComponentAccountDoesNotExists() + "<br/>");
			}
			else if (id == -70)
			{
				warningLabel.setHTML(constants.AccountComponentEmailDoesNotMatchId() + "<br/>");
			}
			else if (id == -80)
			{
				warningLabel.setHTML(constants.AccountComponentAddressDoesnNotExist() + "<br/>");
			}
			else if (id == -90)
			{
				warningLabel.setHTML(constants.AccountComponentTooManyAddresses() + "<br/>");
			}
			else
			{
				warningLabel.setHTML(constants.AccountComponentUnknownError() + " " + id + "<br/>");
			}
		}
		add(new Label("Customer Id: " + accountModel.getId()));

		int gridrows = 0;
		if (accountModel.getId() > 0)
		{
			gridrows = 5;

		}
		else if (accountModel.getId() == 0)
		{
			gridrows = 10;
			if (accountMetaModel.isDisplayCompany()) gridrows++;
			if (accountMetaModel.isDisplaySuburb()) gridrows++;
			if (accountMetaModel.isDisplayState()) gridrows++;
		}
		if (accountMetaModel.isDisplayGender()) gridrows++;
		if (accountMetaModel.isDisplayDOB()) gridrows++;
		Grid detailsGrid = new Grid(gridrows,3);
		add(detailsGrid);

		int gridrow = 0;
		if (accountMetaModel.isDisplayGender()) 
		{
			RadioButton genderMButton = new RadioButton("gender1", constants.AccountComponentMale());
			RadioButton genderFButton = new RadioButton("gender1", constants.AccountComponentFemale());
			elements.put("genderM", genderMButton);
			elements.put("genderF", genderFButton);
			HorizontalPanel genderPanel = new HorizontalPanel();
			genderPanel.add(genderMButton);
			genderPanel.add(genderFButton);

			if (accountModel.getGender().equals("f"))
			{
				genderFButton.setValue(true);
				genderMButton.setValue(false);
			}
			else if (accountModel.getGender().equals("m"))
			{
				genderFButton.setValue(false);
				genderMButton.setValue(true);
			}

			CommonUtils.addGridWidget(handle, gridrow, genderPanel, detailsGrid, "gender", constants.AccountComponentGender(), constants.AccountComponentGenderText());
			gridrow++;
		}

		TextBox firstnameBox = new TextBox(); 
		elements.put("firstname", firstnameBox);
		CommonUtils.addGridWidget(handle, gridrow, firstnameBox, detailsGrid, "firstname", constants.AccountComponentFirstname(), constants.AccountComponentFirstnameText());
		firstnameBox.setText(accountModel.getFirstname());
		gridrow++;

		TextBox lastnameBox = new TextBox(); 
		elements.put("lastname", lastnameBox);
		CommonUtils.addGridWidget(handle, gridrow, lastnameBox, detailsGrid, "lastname", constants.AccountComponentLastname(), constants.AccountComponentLastnameText());
		lastnameBox.setText(accountModel.getLastname());
		gridrow++;

		if (accountMetaModel.isDisplayDOB())
		{
			DateTimeFormat dtformat = DateTimeFormat.getFormat(constants.AccountComponentDateOfBirthFormat());
			TextBox dobBox = new TextBox(); 
			elements.put("dob", dobBox);
			CommonUtils.addGridWidget(handle, gridrow, dobBox, detailsGrid, "dob1", constants.AccountComponentDateOfBirth(), constants.AccountComponentDateOfBirthText() + dtformat.getPattern());
			try {
				dobBox.setText(dtformat.format(accountModel.getDateOfBirth()));
			}
			catch (Exception dte){}
			gridrow++;
		}

		TextBox emailBox = new TextBox(); 
		elements.put("email_address", emailBox);
		CommonUtils.addGridWidget(handle, gridrow, emailBox, detailsGrid, "email_address", constants.AccountComponentEmailAddress(), constants.AccountComponentEmailAddressText());
		emailBox.setText(accountModel.getEmailAddress());
		gridrow++;

		TextBox telephoneBox = new TextBox(); 
		elements.put("telephone", telephoneBox);
		CommonUtils.addGridWidget(handle, gridrow, telephoneBox, detailsGrid, "telephone", constants.AccountComponentTelephoneNumber(), constants.AccountComponentTelephoneNumberText());
		telephoneBox.setText(accountModel.getTelephone());
		gridrow++;

		TextBox faxBox = new TextBox(); 
		elements.put("fax", faxBox);
		CommonUtils.addGridWidget(handle, gridrow, faxBox, detailsGrid, "fax", constants.AccountComponentFaxNumber(), constants.AccountComponentFAXNumberText());
		faxBox.setText(accountModel.getFax());		
		gridrow++;

		if (accountModel.getId() > 0)
		{
			buttonPanel.add(deleteButton);
			buttonPanel.add(new InlineHTML("&nbsp;&nbsp;"));
			Button saveButton = new Button("save", 
					new ClickHandler() {
				public void onClick(ClickEvent event) {
					action = EditAccount;
					submit();
				}}
			);
			saveButton.addStyleName("ComponentLink");
			buttonPanel.add(saveButton);

			add(new HTML("&nbsp;"));

			List<AddressModel> addresses = accountModel.getAddresses();
			int sz = addresses.size();
			Grid grid = new Grid(sz+1, 3);
			grid.getRowFormatter().addStyleName(0, "TableHeader");
			grid.setText(0, 0, constants.AccountComponentPrimary());
			grid.setText(0, 1, constants.AccountComponentAddress());
			grid.setText(0, 2, "Action");

			CellFormatter cf = grid.getCellFormatter();
			cf.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
			cf.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
			cf.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);

			int row = 1;
			for (int i = 0; i<sz+1; i++)
			{
				boolean primary = false;
				AddressModel amodel;
				if (i == 0) {
					amodel = accountModel.getDefaultAddress();
					primary = true;
				}
				else {
					amodel = addresses.get(i-1);
					if (amodel.getId() == accountModel.getDefaultAddress().getId()) continue;
				}

				int k = row % 2;
				String rowStyle = "Even";
				if (k > 0) rowStyle = "Odd";
				grid.getRowFormatter().addStyleName(row, rowStyle);	

				String strPrimary = commonConstants.No();
				if (primary) strPrimary = commonConstants.Yes();
				grid.setText(row, 0, strPrimary);

				String strAddress = "";
				if (accountMetaModel.isDisplayCompany()) strAddress += amodel.getCompany() + "<br/>";
				strAddress += amodel.getFirstname() + "&nbsp;" + amodel.getLastname() + "<br/>";
				strAddress += amodel.getStreet() + "<br/>";
				if (accountMetaModel.isDisplaySuburb()) strAddress += amodel.getSuburb() + "<br/>";
				strAddress += amodel.getCity();
				if (accountMetaModel.isDisplayState()) strAddress += ", " + amodel.getState() + " ";
				strAddress += amodel.getPostcode() + "<br/>";
				strAddress += amodel.getCountry();
				InlineHTML addressLabel = new InlineHTML(strAddress);
				grid.setWidget(row, 1, addressLabel);

				HorizontalPanel actionPanel = new HorizontalPanel();

				InlineLabel editLabel = new InlineLabel("edit");
				editLabel.setStyleName("ComponentLink");
				editLabel.addStyleName("index:" + amodel.getId());
				editLabel.addClickHandler(editAddressHandler);
				actionPanel.add(editLabel);
				actionPanel.add(new InlineLabel(", "));

				InlineLabel deleteLabel = new InlineLabel("delete");
				deleteLabel.setStyleName("ComponentLink");
				deleteLabel.addStyleName("index:" + amodel.getId());
				deleteLabel.addClickHandler(deleteAddressHandler);
				actionPanel.add(deleteLabel);

				grid.setWidget(row, 2, actionPanel);

				row++;
			}		
			add(grid);
			Button addButton = new Button("add address", 
					new ClickHandler() {
				public void onClick(ClickEvent event) {
					if (accountModel.getAddresses().size() < accountMetaModel.getAddressBookEntriesMax()) 
					{
						AddressModel addressModel = new AddressModel();
						addressModel.setCountry(accountModel.getDefaultAddress().getCountry());
						editDialogBox(addressModel);
					}
					else
					{
						Window.alert("Maximum # of Addresses has been reached: " + accountMetaModel.getAddressBookEntriesMax());
					}
				}}
			);
			add(addButton);
		}
		else
		{
			Button saveAsNewButton = new Button("save as new",
					new ClickHandler() {
				public void onClick(ClickEvent event) {
					action = CreateAccount;
					submit();
				}}
			);
			saveAsNewButton.addStyleName("ComponentLink");
			buttonPanel.add(saveAsNewButton);

			AddressModel addressModel = accountModel.getDefaultAddress();

			gridrow = displayAddressWidgets(gridrow, detailsGrid, constants, addressModel, false);

			CheckBox newsletterBox = new CheckBox();
			elements.put("newsletter", newsletterBox);
			CommonUtils.addGridWidget(handle, gridrow, newsletterBox, detailsGrid, "newsletter", constants.AccountComponentNewsletter(),"");
			newsletterBox.setValue(accountModel.isNewsletter());
		}
		String focusName = "firstname";
		if (accountMetaModel.isDisplayGender()) focusName = "genderM";
		focusWidget = (FocusWidget)elements.get(focusName);
		onBuilt();
	}


	/**
	 * validate prior to form submission
	 */
	public void submit() 
	{
		AccountMetaModel accountMetaModel = AdminComponentController.accountComponent.getAccountMetaModel();
		AccountModel accountModel = AdminComponentController.accountComponent.getAccountModel();
		try {
			GWTCommerceConstants constants = adminController.getAdminConstants();
			GWTCommerceCommonConstants commonConstants = controller.getCommonConstants();
			//Validations
			StringBuffer warningText = new StringBuffer();

			RadioButton genderMButton = (RadioButton) elements.get("genderM");
			RadioButton genderFButton = (RadioButton) elements.get("genderF");
			if (genderMButton != null && genderFButton != null) {
				if (!genderMButton.getValue() && !genderFButton.getValue()) {
					warningText.append(constants.AccountComponentGenderError());
				}
				else if (genderMButton.getValue()) {
					elements.put("gender", new InlineLabel("m"));
				}
				else if (genderFButton.getValue()) {
					elements.put("gender", new InlineLabel("f"));
				}
			}

			TextBox firstnameBox = (TextBox)elements.get("firstname");
			if (firstnameBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, firstnameBox, 
						constants.AccountComponentFirstname(), accountMetaModel.getEntryFirstnameLengthMin());
			}

			TextBox lastnameBox = (TextBox)elements.get("lastname");
			if (lastnameBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, lastnameBox, 
						constants.AccountComponentLastname(), accountMetaModel.getEntryLastnameLengthMin());
			}

			genderMButton = (RadioButton) addressElements.get("genderM");
			genderFButton = (RadioButton) addressElements.get("genderF");
			if (genderMButton != null && genderFButton != null) {
				if (!genderMButton.getValue() && !genderFButton.getValue()) {
					warningText.append(constants.AccountComponentGenderError());
				}
				else if (genderMButton.getValue()) {
					addressElements.put("gender", new InlineLabel("m"));
				}
				else if (genderFButton.getValue()) {
					addressElements.put("gender", new InlineLabel("f"));
				}
			}

			firstnameBox = (TextBox)addressElements.get("firstname");
			if (firstnameBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, firstnameBox, 
						constants.AccountComponentFirstname(), accountMetaModel.getEntryFirstnameLengthMin());
			}

			lastnameBox = (TextBox)addressElements.get("lastname");
			if (lastnameBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, lastnameBox, 
						constants.AccountComponentLastname(), accountMetaModel.getEntryLastnameLengthMin());
			}

			TextBox dobBox = (TextBox)elements.get("dob");
			if (dobBox != null) {
				String strDOB = dobBox.getText();
				if (strDOB != null && strDOB.length() > 0) {
					try {
						DateTimeFormat dtformat = DateTimeFormat.getFormat(constants.AccountComponentDateOfBirthFormat());
						Date dateDOB = dtformat.parse(strDOB);
						dobBox.setText(dtformat.format(dateDOB));
						accountModel.setDateOfBirth(dateDOB);
					}
					catch(Exception exception) {
						if (warningText.length() > 0)warningText.append("\n");
						warningText.append(constants.AccountComponentDateOfBirthError());
					}
				}				
			}

			TextBox emailBox = (TextBox) elements.get("email_address");
			if (emailBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, emailBox, 
						constants.AccountComponentEmailAddress(), accountMetaModel.getEntryEmailAddressLengthMin());
			}

			TextBox streetBox = (TextBox) addressElements.get("street_address");
			if (streetBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, streetBox, 
						constants.AccountComponentStreetAddress(), accountMetaModel.getEntryStreetAddressLengthMin());
			}

			TextBox postCodeBox = (TextBox) addressElements.get("postcode");
			if (postCodeBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, postCodeBox, 
						constants.AccountComponentPostCode(), accountMetaModel.getEntryPostCodeLengthMin());
			}

			TextBox cityBox = (TextBox) addressElements.get("city");
			if (cityBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, cityBox, 
						constants.AccountComponentCity(), accountMetaModel.getEntryCityLengthMin());
			}

			TextBox telephoneBox = (TextBox) elements.get("telephone");
			if (telephoneBox != null) {
				warningText = CommonUtils.lengthWarning(commonConstants, warningText, telephoneBox, 
						constants.AccountComponentTelephoneNumber(), accountMetaModel.getEntryTelephoneNumberLengthMin());
			}

			if (warningText.length() > 0)
				Window.alert(warningText.toString());
			else
			{
				build(true);
			}
		}
		catch (Exception e) 
		{
			GWT.log("EditAccountComponent.submit", e);
		}
	}

	public int displayAddressWidgets(int gridrow, Grid grid, GWTCommerceConstants constants, AddressModel addressModel, boolean boolName)
	{
		addressElements.clear();
		addressElements.put("addressId", new InlineLabel(String.valueOf(addressModel.getId())));

		if (accountMetaModel.isDisplayCompany())
		{
			TextBox companyBox = new TextBox(); 
			addressElements.put("company", companyBox);
			CommonUtils.addGridWidget(handle,gridrow, companyBox, grid, "company", constants.AccountComponentCompany(), constants.AccountComponentCompanyText());
			companyBox.setText(addressModel.getCompany());
			gridrow++;
		}

		if (boolName) {
			if (accountMetaModel.isDisplayGender()) 
			{
				RadioButton genderMButton = new RadioButton("gender1", constants.AccountComponentMale());
				RadioButton genderFButton = new RadioButton("gender1", constants.AccountComponentFemale());
				addressElements.put("genderM", genderMButton);
				addressElements.put("genderF", genderFButton);
				HorizontalPanel genderPanel = new HorizontalPanel();
				genderPanel.add(genderMButton);
				genderPanel.add(genderFButton);

				if (accountModel.getGender().equals("f"))
				{
					genderFButton.setValue(true);
					genderMButton.setValue(false);
				}
				else if (accountModel.getGender().equals("m"))
				{
					genderFButton.setValue(false);
					genderMButton.setValue(true);
				}

				CommonUtils.addGridWidget(handle, gridrow, genderPanel, grid, "gender", constants.AccountComponentGender(), constants.AccountComponentGenderText());
				gridrow++;
			}

			TextBox firstnameBox = new TextBox(); 
			addressElements.put("firstname", firstnameBox);
			CommonUtils.addGridWidget(handle, gridrow, firstnameBox, grid, "firstname", constants.AccountComponentFirstname(), constants.AccountComponentFirstnameText());
			firstnameBox.setText(accountModel.getFirstname());
			gridrow++;

			TextBox lastnameBox = new TextBox(); 
			addressElements.put("lastname", lastnameBox);
			CommonUtils.addGridWidget(handle, gridrow, lastnameBox, grid, "lastname", constants.AccountComponentLastname(), constants.AccountComponentLastnameText());
			lastnameBox.setText(accountModel.getLastname());
			gridrow++;
		}
		countryListBox = new ListBox();
		addressElements.put("country", countryListBox);
		countryListBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				if (AdminComponentController.accountComponent.getAccountMetaModel().isDisplayState())
				{
					CountryModel cmodel = AdminComponentController.accountComponent.getAccountMetaModel().getCountryModels().get(countryListBox.getSelectedIndex());
					String countryName = cmodel.getName();
					if (accountMetaModel.isDisplayState()) CommonUtils.updateStateListBox(countryName, null, AdminComponentController.accountComponent.getAccountMetaModel().getCountryModels(), stateListBox);	
				}
			}
		});
		CommonUtils.addGridWidget(handle, gridrow, countryListBox, grid, "country", constants.AccountComponentCountry(), constants.AccountComponentCountryText());

		Iterator<CountryModel> iter = accountMetaModel.getCountryModels().iterator();
		int i = 0;
		while(iter.hasNext())
		{
			CountryModel cmodel = iter.next();
			countryListBox.addItem(cmodel.getName(),cmodel.getName());
			if (cmodel.getName().equals(addressModel.getCountry()))
				countryListBox.setItemSelected(i, true);
			else
				countryListBox.setItemSelected(i, false);
			i++;
		}

		gridrow++;

		TextBox streetBox = new TextBox(); 
		addressElements.put("street_address", streetBox);
		CommonUtils.addGridWidget(handle, gridrow, streetBox, grid, "street_address", constants.AccountComponentStreetAddress(), constants.AccountComponentStreetAddressText());
		streetBox.setText(addressModel.getStreet());
		gridrow++;

		if (accountMetaModel.isDisplaySuburb())
		{
			TextBox suburbBox = new TextBox(); 
			addressElements.put("suburb", suburbBox);
			CommonUtils.addGridWidget(handle, gridrow, suburbBox, grid, "suburb", constants.AccountComponentSuburb(), constants.AccountComponentSuburbText());
			suburbBox.setText(addressModel.getSuburb());
			gridrow++;
		}

		TextBox cityBox = new TextBox(); 
		addressElements.put("city", cityBox);
		CommonUtils.addGridWidget(handle, gridrow, cityBox, grid, "city", constants.AccountComponentCity(), constants.AccountComponentCityText());
		cityBox.setText(addressModel.getCity());
		gridrow++;

		if (accountMetaModel.isDisplayState())
		{
			stateListBox = new ListBox();
			addressElements.put("state", stateListBox);
			CommonUtils.addGridWidget(handle, gridrow, stateListBox, grid, "state", constants.AccountComponentState(), constants.AccountComponentStateText());
			CommonUtils.updateStateListBox(addressModel.getCountry(), addressModel.getState(), accountMetaModel.getCountryModels(), stateListBox);
			gridrow++;
		}

		TextBox postCodeBox = new TextBox(); 
		addressElements.put("postcode", postCodeBox);
		CommonUtils.addGridWidget(handle, gridrow, postCodeBox, grid, "postcode", constants.AccountComponentPostCode(), constants.AccountComponentPostCodeText());
		postCodeBox.setText(addressModel.getPostcode());
		gridrow++;

		return gridrow;
	}

	public boolean updateFromHistoryParameters(String[] params)
	{
		selectedAccountId = 0;
		try {
			selectedGroupId = Integer.parseInt(params[1]);
			AccountsGroupComponent accountsGroupComponent = (AccountsGroupComponent) controller.getComponent("AccountsGroupComponent");
			accountsGroupComponent.setSelectedGroupModel(selectedGroupId);	
			accountsGroupComponent.setSelectedInGUI();
			adminController.getNavigationStackPanel().showStack(accountsGroupComponent.getIndex());	

			selectedAccountId = Integer.parseInt(params[2]);
		}
		catch (Exception e) {}

		return super.updateFromHistoryParameters(params);
	}


	protected ClickHandler deleteHandler= new ClickHandler() {
		public void onClick(ClickEvent event)
		{
			if (Window.confirm("Delete Account?")) {
				action = DeleteAccount;
				build(true);
			}
		}
	};

	protected ClickHandler backHandler= new ClickHandler() {
		public void onClick(ClickEvent event)
		{
			String history = "AccountsComponent--" + selectedGroupId;
			onSelection(history);
		}
	};

	protected ClickHandler deleteAddressHandler= new ClickHandler() {
		public void onClick(ClickEvent event)
		{
			if (Window.confirm("Delete Address?")) {
				Widget source = (Widget)event.getSource();
				String stylenames = source.getStyleName();
				int loc = stylenames.indexOf("index:");
				stylenames = stylenames.substring(loc+6);
				loc = stylenames.indexOf(" ");
				if (loc > -1) stylenames = stylenames.substring(0, loc);
				int id = Integer.parseInt(stylenames);

				action = DeleteAddress;
				addressElements.clear();
				addressElements.put("addressId", new InlineLabel(String.valueOf(id)));
				build(true);	
			}
		}
	};

	protected ClickHandler editAddressHandler= new ClickHandler() {
		public void onClick(ClickEvent event)
		{
			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int id = Integer.parseInt(stylenames);
			AddressModel addressModel = accountModel.getAddressById(id);
			editDialogBox(addressModel);
		}
	};

	protected void editDialogBox(AddressModel addressModel) {
		dialogBox = new DialogBox();
		dialogBox.setStyleName(getHandle()+ "DialogBox");
		dialogBox.addStyleName("DialogBox");
		dialogBox.setWidth("400px");
		String editText = "";
		if (addressModel.getId() == 0) {
			editText = "save as new";
			dialogBox.setText(adminController.getAdminConstants().AccountComponentAddAddress());
		}
		else {
			editText = "save";
			dialogBox.setText(adminController.getAdminConstants().AccountComponentEditAddress());
		}

		FlowPanel dialogContents = new FlowPanel();

		int gridrows = 6;
		if (accountMetaModel.isDisplayCompany()) gridrows++;
		if (accountMetaModel.isDisplayGender()) gridrows++;
		if (accountMetaModel.isDisplaySuburb()) gridrows++;
		if (accountMetaModel.isDisplayState()) gridrows++;
		Grid grid = new Grid(gridrows,3);
		displayAddressWidgets(0, grid, adminController.getAdminConstants(), addressModel, true);
		dialogContents.add(grid);

		HorizontalPanel buttonPanel = new HorizontalPanel();

		Button closeButton = new Button("close",
				new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});
		buttonPanel.add(closeButton);
		buttonPanel.add(new InlineHTML("&nbsp;&nbsp;"));

		Button editButton = new Button(editText,
				new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
				action = AddressBook;
				submit();
			}
		});
		buttonPanel.add(editButton);
		dialogContents.add(buttonPanel);

		dialogBox.setWidget(dialogContents);
		dialogBox.center();
		dialogBox.show();
		String focusName = "firstname";
		if (accountMetaModel.isDisplayCompany()) focusName = "company";
		else if (accountMetaModel.isDisplayGender()) focusName = "genderM";
		FocusWidget widget = (FocusWidget)addressElements.get(focusName);
		widget.setFocus(true);
	}

	public void build(JSONValue jsonValue)
	throws Exception
	{
		super.build(jsonValue);
		if (accountModel.getId() == -1)
		{
			String history = "AccountsComponent--2";
			onSelection(history);
		}
	}
}
